package com.Hsu.mq.mqserver.core;

/**
 * @author Hsu琛君珩
 * @ClassName:Message
 * @date 2024-02-09
 * @apiNote
 * @Version: v1.0
 */

import lombok.Data;

import java.io.Serializable;
import java.util.Arrays;
import java.util.UUID;

/**
 * 一条要传递的消息
 * 这个 Message 对象要能在网络上传输，并且需要能写入到文件中
 * 因此需要对此进行序列化和反序列化，直接用标准库里的即可
 */
@Data
public class Message implements Serializable {
    //private static final long serialVersionUID=1L;//用来验证版本的

    //这两个是核心部分
    //属性部分 BasicProperties
    private BasicProperties basicProperties = new BasicProperties();//防止空指针
    //正文部分 byte[] 正文是支持二进制数据
    private byte[] body;

    //辅助属性
    //持久化，后续可能存储到文件中，想在文件中具体位置找到某个信息，就使用下面两个偏移量
    // [offsetBeg,offsetEnd) 前闭后开区间
    //这两个属性不需要序列化保存到文件中，因为一旦写入到文件中，所在位置就固定了，不需要单独存储
    //这两个属性存在的目的就是为了让内存中的 Message 对象能够快速找到对应硬盘上的 Message 的位置
    private transient long offsetBeg = 0;//消息数据的开头距离文件开头的位置(字节)
    private transient long offsetEnd = 0;//消息数据的结尾距离文件开头的位置(字节)

    //使用这个表示该消息在文件中是否为有效信息 (逻辑删除)
    // 0x1 表示有效，0x0 表示无效
    private byte isValid = 0x1;

    //创建一个工厂方法，封装创建 Message 对象的过程
    //创建的 Message 对象会自动生成唯一的 MessageId
    public static Message createMessageWithId(String routingKey, BasicProperties basicProperties, byte[] body) {
        Message message = new Message();
        if (basicProperties != null) {
            message.setBasicProperties(basicProperties);
        }
        //此处生成的 MessageId 以 M- 作为前缀
        message.setMessageId("M-" + UUID.randomUUID());
        //万一 routingKey 和 basicProperties 里面的 routingKey 都冲突了就以外面的为主
        message.setRoutingKey(routingKey);
        message.body = body;
        //此处是把 body 和 basicProperties 先设置好，这两个是核心
        //而 offsetBeg offsetEnd isValid 是消息持久化时才用，把消息写入文件时再设定
        //此处只是在内存中创建一个 Message 对象
        return message;
    }

    public String getMessageId() {
        return basicProperties.getMessageId();
    }

    public void setMessageId(String messageId) {
        basicProperties.setMessageId(messageId);
    }

    public String getRoutingKey() {
        return basicProperties.getRoutingKey();
    }

    public void setRoutingKey(String routingKey) {
        basicProperties.setRoutingKey(routingKey);
    }

    public int getDeliverMode() {
        return basicProperties.getDeliverMode();
    }

    public void setDeliverMode(int mode) {
        basicProperties.setDeliverMode(mode);
    }

    public BasicProperties getBasicProperties() {
        return basicProperties;
    }

    public void setBasicProperties(BasicProperties basicProperties) {
        this.basicProperties = basicProperties;
    }

    public byte[] getBody() {
        return body;
    }

    public void setBody(byte[] body) {
        this.body = body;
    }

    public long getOffsetBeg() {
        return offsetBeg;
    }

    public void setOffsetBeg(long offsetBeg) {
        this.offsetBeg = offsetBeg;
    }

    public long getOffsetEnd() {
        return offsetEnd;
    }

    public void setOffsetEnd(long offsetEnd) {
        this.offsetEnd = offsetEnd;
    }

    public byte getIsValid() {
        return isValid;
    }

    public void setIsValid(byte isValid) {
        this.isValid = isValid;
    }

    @Override
    public String toString() {
        return "Message{" +
                "basicProperties=" + basicProperties +
                ", body=" + Arrays.toString(body) +
                ", offsetBeg=" + offsetBeg +
                ", offsetEnd=" + offsetEnd +
                ", isValid=" + isValid +
                '}';
    }
}